package util;


/*Hex = Nibble = 4 bits*/
/*MSB  more  significant bit  --left  4 bits   high  most,  it stores the event number for X-event*/
/*LSB  less  significant bit  --right 4 bits   low   least, it stores the event number for X-odd and X-odd = x-event+1*/
public class HexYZXArray {
	
	/* Byte array of data stored in this holder. Possibly a light map or some chunk data. Data is accessed in 4-bit pieces. */
	public final byte[] byteArray;

	/* Log base 2 of the chunk height (128); applied as a shift on Z coordinate */
	/* Log base 2 of the chunk height (128); applied as a shift on ZX(16*16) coordinate */
	private static final int INDEX_MAX_LOG2_X = 4;
	private static final int INDEX_MAX_LOG2_Z = 4;
	private static final int INDEX_INCREM_Z = INDEX_MAX_LOG2_X;
	private static final int INDEX_INCREM_Y = INDEX_MAX_LOG2_X + INDEX_MAX_LOG2_Z;

	/* Size of 4 bits */
	public HexYZXArray(int nibbleSize) {
		this.byteArray = new byte[nibbleSize >> 1];
	}

	public HexYZXArray(byte[] byteArray) {
		this.byteArray = byteArray;
	}

	/*
	 * Returns the nibble of data corresponding to the passed in x, y, z. 
	 * y is at most 6 bits, 0-63
	 * z is at most 4 bits. 0-15
	 * Index  = Y xxxxxxxx Z xxxx X xxxx
	 * MSBIndicator the last bit of X
	 */
	public int get(int x, int y, int z) {
		int hexIndex = toHexIndex(x, y, z);
		int byteIndex = hexIndex >> 1;
		int MSBYN = hexIndex & 1;
		if (MSBYN == 0) {
			return this.byteArray[byteIndex] & 15;// 00001111
		} else {
			return this.byteArray[byteIndex] >> 4 & 15;
		}
	}

	public void set(int x, int y, int z, int value) {
		int hexIndex = toHexIndex(x, y, z);
		int byteIndex = hexIndex >> 1;
		int MSBYN = hexIndex & 1;

		if (MSBYN == 0) {
			// 240 =B11110000 (128(1000 0000)+64(01000000)+32(00100000)+16(000100000) = 192)
			this.byteArray[byteIndex] = (byte) (this.byteArray[byteIndex] & 240 | value & 15);
		} else {
			this.byteArray[byteIndex] = (byte) (this.byteArray[byteIndex] & 15 | (value & 15) << 4);
		}
	}

	/* Y*Z*X = 16* 16 *16= 4096 if max size of each dimension is 16(0000- 1111) */
	private int toHexIndex(int x, int y, int z) {
		return y << INDEX_INCREM_Y | z << INDEX_INCREM_Z | x;
	}
	
	//------------------------------------------------------------------
	public int getHexSize(){
		return this.byteArray.length*2;
	}
	
	public int getByteSize(){
		return this.byteArray.length;
	}	
	
	public static byte[] hexStringToByteArray(String s) {
	    int len = s.length();
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
}
